package cn.qingyun.gis.modules.takeaway.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.qingyun.gis.modules.express.constant.ExpressStatus;
import cn.qingyun.gis.modules.express.util.SyncTool;
import cn.qingyun.gis.modules.init.system.entity.SysUser;
import cn.qingyun.gis.modules.init.system.mapper.SysUserMapper;
import cn.qingyun.gis.modules.init.utils.JwtUtil;
import cn.qingyun.gis.modules.takeaway.entity.TakeawayProofread;
import cn.qingyun.gis.modules.takeaway.entity.dto.TakeawayExportTotalDto;
import cn.qingyun.gis.modules.takeaway.mapper.TakeawayInfoMapper;
import cn.qingyun.gis.modules.takeaway.service.ITakeawayAttachmentService;
import cn.qingyun.gis.modules.takeaway.service.ITakeawayDataInitService;
import cn.qingyun.gis.modules.takeaway.service.ITakeawayInfoService;
import cn.qingyun.gis.modules.takeaway.service.ITakeawayProofreadService;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

@Service
@Slf4j
public class ITakeawayDataInitServiceImpl implements ITakeawayDataInitService {
    @Resource
    private ITakeawayProofreadService iTakeawayProofreadService;
    @Resource
    private ITakeawayInfoService iTakeawayInfoService;
    @Resource
    private ITakeawayAttachmentService iTakeawayAttachmentService;
    @Resource
    private HttpServletResponse response;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private TakeawayInfoMapper takeawayInfoMapper;

    @Override
    public void initExcelData(MultipartFile file) {
        log.debug("开始导入");
        new Thread(() -> {
            try {
                List<TakeawayProofread> addDatas = Lists.newArrayList();
                EasyExcelFactory.read(file.getInputStream(), TakeawayProofread.class, new ReadListener<TakeawayProofread>() {
                    @Override
                    public void onException(Exception exception, AnalysisContext context) {
                        if (exception instanceof ExcelDataConvertException) {
                            log.error("解析异常, 行：{}", ((ExcelDataConvertException) exception).getRowIndex());
                        } else {
                            log.error("解析异常, {}", exception.getClass().getName());
                        }
                    }

                    @Override
                    public void invoke(TakeawayProofread data, AnalysisContext context) {
                        data.setProvince("山东");
                        data.setKwStatus(ExpressStatus.UN_PROOFED);
                        data.setCreateTime(DateUtil.date());
                        data.setUpdateTime(DateUtil.date());
                        addDatas.add(data);

                        if (addDatas.size() == 100) {
                            iTakeawayProofreadService.saveBatch(addDatas);
                            addDatas.clear();
                        }
                    }

                    @Override
                    public void doAfterAllAnalysed(AnalysisContext context) {
                        iTakeawayProofreadService.saveBatch(addDatas);
                        log.debug("导入完成");
                    }
                }).sheet().doReadSync();

            } catch (IOException e) {
                log.error("导入失败", e);
            }
        }).start();
    }

    @Override
    public void formatting() {
        iTakeawayProofreadService.remove(new QueryWrapper<>());
        iTakeawayInfoService.remove(new QueryWrapper<>());
        iTakeawayAttachmentService.remove(new QueryWrapper<>());
    }

    @SneakyThrows
    @Override
    public void exportTakeawayTotal(HttpServletRequest request) {
        response.setContentType("application/vnd.ms-excel");
        String fileName = "垂类地址信息明细表";
        response.setHeader("content-disposition", String.format("attachment;filename=%s.xlsx", new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1) + DateUtil.now()));
        // 获取当前用户信息
        String currentUserName = JwtUtil.getUserNameByToken(request);
        // 根据用户信息查询区域编码
        SysUser user = sysUserMapper.selectOne(new QueryWrapper<SysUser>().lambda().
                select(SysUser::getRegionCode).
                eq(SysUser::getUsername, currentUserName));
        log.debug("当前登录用户信息：{} 以及相应配置地市权限编码{}", currentUserName, user.getRegionCode());
        String regionCode;
        if ("0000SD".equals(user.getRegionCode())) { // 当前省级配置工号
            regionCode = null;
        } else {
            regionCode = user.getRegionCode();
        }
        // 根据分页进行多线程并发导入
        int count = iTakeawayProofreadService.count(new QueryWrapper<>());
        try (ExcelWriter excelWriter = EasyExcelFactory.write(response.getOutputStream()).build()) {
            // 此处使用导入实体类充当导出
            WriteSheet writeSheet = EasyExcelFactory.writerSheet(0, "全量数据").head(TakeawayExportTotalDto.class).build();
            int pages = (count / 1000) + 1;
            //并发导出
            SyncTool.doSync(pages, i -> {
                Page<TakeawayExportTotalDto> page = new Page<>(i, 1000);
                IPage<TakeawayExportTotalDto> infoTotalDtos = takeawayInfoMapper.selectTakeawayTotal(page, null, regionCode);
                synchronized (excelWriter) {
                    excelWriter.write(infoTotalDtos.getRecords(), writeSheet);
                }
            });
        }
        log.debug("已成功导出{}条外卖地址全量数据", count);
    }
}
